home *** CD-ROM | disk | FTP | other *** search
- RCS_ID_C="$Id: amiga_syscalls.c,v 3.5 1994/03/22 08:41:36 jraja Exp $";
- /*
- * Copyright (c) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>
- * Helsinki University of Technology, Finland.
- * All rights reserved.
- *
- * Created: Sun Feb 14 18:35:48 1993 too
- * Last modified: Wed Feb 16 01:18:32 1994 jraja
- *
- * HISTORY
- * $Log: amiga_syscalls.c,v $
- * Revision 3.5 1994/03/22 08:41:36 jraja
- * Added calls to the libPtr->fdCallback to the appropriate places.
- *
- * Revision 3.4 1994/02/15 23:18:42 jraja
- * Changed sdFind() to return the sd via LONG * instead of ULONG * to be
- * consistent with API types.
- *
- * Revision 3.3 1994/01/07 15:40:29 too
- * Bug fixes after revision 3.1. Now tested.
- *
- * Revision 3.2 1994/01/06 13:39:11 too
- * Moved send and recv functions to amiga_sendrecv.c
- *
- * Revision 3.1 1994/01/04 14:32:29 too
- * Added function sdFind(). Revised socket() and accept() to use sdFind()
- * and socket usage bitmask.
- *
- * Revision 1.25 1993/06/04 11:16:15 jraja
- * Fixes for first public release.
- *
- */
-
- #include <conf.h>
-
- #include <sys/param.h>
- #include <sys/systm.h>
- #include <sys/malloc.h>
- #include <sys/mbuf.h>
- #include <sys/protosw.h>
- #include <sys/socket.h>
- #include <sys/socketvar.h>
- #include <sys/synch.h>
- #include <sys/errno.h>
-
- #include <exec/types.h>
- #include <exec/libraries.h>
- #include <exec/semaphores.h>
-
- #include <api/amiga_api.h>
- #include <api/amiga_libcallentry.h>
- #include <sockargs.h>
-
- #include <amitcp/socketbasetags.h>
-
- #include <kern/uipc_socket_protos.h>
- #include <kern/uipc_socket2_protos.h>
-
-
- LONG SAVEDS RAF4(_socket,
- struct SocketBase *, libPtr, a6,
- LONG, domain, d0,
- LONG, type, d1,
- LONG, protocol, d2)
-
- #if 0
- {
- #endif
-
- struct socket *so;
- LONG fd, error;
-
- CHECK_TASK();
-
- if (error = sdFind(libPtr, &fd))
- goto Return;
-
- ObtainSyscallSemaphore(libPtr);
- error = socreate(domain, &so, type, protocol);
- ReleaseSyscallSemaphore(libPtr);
-
- if (! error) {
- /*
- * Tell the link library about the new fd
- */
- if (libPtr->fdCallback)
- error = libPtr->fdCallback(fd, FDCB_ALLOC);
- if (! error) {
- so->so_refcnt = 1; /* reference count is pure AmiTCP addition */
- libPtr->dTable[fd] = so;
- FD_SET(fd, (fd_set *)(libPtr->dTable + libPtr->dTableSize));
- }
- }
-
- Return: API_STD_RETURN(error, fd);
- }
-
-
- LONG SAVEDS RAF4(_bind,
- struct SocketBase *, libPtr, a6,
- LONG, s, d0,
- caddr_t, name, a0,
- LONG, namelen, d1)
- #if 0
- {
- #endif
-
- struct socket *so;
- struct mbuf *nam;
- LONG error;
-
- CHECK_TASK();
- ObtainSyscallSemaphore(libPtr);
-
- if (error = getSock(libPtr, s, &so))
- goto Return;
- if (error = sockArgs(&nam, name, namelen, MT_SONAME))
- goto Return;
- error = sobind(so, nam);
- m_freem(nam);
-
- Return:
- ReleaseSyscallSemaphore(libPtr);
- API_STD_RETURN(error, 0);
- }
-
- LONG SAVEDS RAF3(_listen,
- struct SocketBase *, libPtr, a6,
- LONG, s, d0,
- LONG, backlog, d1)
- #if 0
- {
- #endif
-
- struct socket *so;
- LONG error;
-
- CHECK_TASK();
- ObtainSyscallSemaphore(libPtr);
-
- if (error = getSock(libPtr, s, &so))
- goto Return;
- error = solisten(so, backlog);
-
- Return:
- ReleaseSyscallSemaphore(libPtr);
- API_STD_RETURN(error, 0);
-
- }
-
- LONG SAVEDS RAF4(_accept,
- struct SocketBase *, libPtr, a6,
- LONG, s, d0,
- caddr_t, name, a0,
- ULONG *, anamelen, a1)
- #if 0
- {
- #endif
-
- struct socket *so;
- struct mbuf *nam;
- spl_t old_spl;
- LONG error, fd;
-
- CHECK_TASK();
- ObtainSyscallSemaphore(libPtr);
-
- if (error = getSock(libPtr, s, &so))
- goto Return;
-
- old_spl = splnet();
- if ((so->so_options & SO_ACCEPTCONN) == 0) {
- error = EINVAL;
- goto Return_spl;
- }
- if ((so->so_state & SS_NBIO) && so->so_qlen == 0) {
- error = EWOULDBLOCK;
- goto Return_spl;
- }
- while (so->so_qlen == 0 && so->so_error == 0) {
- if (so->so_state & SS_CANTRCVMORE) {
- so->so_error = ECONNABORTED;
- break;
- }
- if (error = tsleep(libPtr, (caddr_t)&so->so_timeo, netcon, NULL)) {
- goto Return_spl;
- }
- }
- if (so->so_error) {
- error = so->so_error;
- so->so_error = 0;
- goto Return_spl;
- }
-
- if (error = sdFind(libPtr, &fd)) {
- goto Return_spl;
- }
-
- /*
- * Tell the link library about the new fd
- */
- if (libPtr->fdCallback)
- if (error = libPtr->fdCallback(fd, FDCB_ALLOC))
- goto Return_spl;
-
- {
- struct socket *aso = so->so_q;
- if (soqremque(aso, 1) == 0)
- panic("accept");
- so = aso;
- }
-
- libPtr->dTable[fd] = so;
- FD_SET(fd, (fd_set *)(libPtr->dTable + libPtr->dTableSize));
- so->so_refcnt = 1; /* pure AmiTCP addition */
-
- nam = m_get(M_WAIT, MT_SONAME);
- (void)soaccept(so, nam); /* is this always successful */
- if (name) {
- if (*anamelen > nam->m_len)
- *anamelen = nam->m_len;
- /* SHOULD COPY OUT A CHAIN HERE */
- aligned_bcopy(mtod(nam, caddr_t), (caddr_t)name, (u_int)*anamelen);
- }
- m_freem(nam);
-
- Return_spl:
- splx(old_spl);
-
- Return:
- ReleaseSyscallSemaphore(libPtr);
- API_STD_RETURN(error, fd);
- }
-
- LONG SAVEDS RAF4(_connect,
- struct SocketBase *, libPtr, a6,
- LONG, s, d0,
- caddr_t, name, a0,
- LONG, namelen, d1)
- #if 0
- {
- #endif
-
- /*register*/ struct socket *so;
- struct mbuf *nam;
- LONG error;
- spl_t old_spl;
-
- CHECK_TASK();
- ObtainSyscallSemaphore(libPtr);
-
- if (error = getSock(libPtr, s, &so))
- goto Return;
- if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
- error = EALREADY;
- goto Return;
- }
- if (error = sockArgs(&nam, name, namelen, MT_SONAME))
- goto Return;
- error = soconnect(so, nam);
- if (error)
- goto bad;
- if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
- m_freem(nam);
- error = EINPROGRESS;
- goto Return;
- }
- old_spl = splnet();
- while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0)
- if (error = tsleep(libPtr,(caddr_t)&so->so_timeo, netcon, NULL))
- break;
- if (error == 0) {
- error = so->so_error;
- so->so_error = 0;
- }
- splx(old_spl);
- bad:
- so->so_state &= ~SS_ISCONNECTING;
- m_freem(nam);
- if (error == ERESTART)
- error = EINTR;
-
- Return:
- ReleaseSyscallSemaphore(libPtr);
- API_STD_RETURN(error, 0);
-
- }
-
- LONG SAVEDS RAF3(_shutdown,
- struct SocketBase *, libPtr, a6,
- LONG, s, d0,
- LONG, how, d1)
- #if 0
- {
- #endif
-
- struct socket *so;
- LONG error;
-
- CHECK_TASK();
- ObtainSyscallSemaphore(libPtr);
-
- if (error = getSock(libPtr, s, &so))
- goto Return;
-
- error = soshutdown(so, how);
-
- Return:
- ReleaseSyscallSemaphore(libPtr);
- API_STD_RETURN(error, 0);
- }
-
- LONG SAVEDS RAF6(_setsockopt,
- struct SocketBase *, libPtr, a6,
- LONG, s, d0,
- LONG, level, d1,
- LONG, name, d2,
- caddr_t, val, a0,
- ULONG, valsize, d3)
- #if 0
- {
- #endif
-
- struct socket *so;
- struct mbuf *m = NULL;
- LONG error;
-
- CHECK_TASK();
- ObtainSyscallSemaphore(libPtr);
-
- if (error = getSock(libPtr, s, &so))
- goto Return;
- if (valsize > MLEN) { /* unsigned catches negative values */
- error = EINVAL;
- goto Return;
- }
- if (val) {
- m = m_get(M_WAIT, MT_SOOPTS);
- if (m == NULL) {
- error = ENOBUFS;
- goto Return;
- }
- bcopy(val, mtod(m, caddr_t), valsize); /* aligned ? */
- m->m_len = (int)valsize;
- }
- error = sosetopt(so, level, name, m);
-
- Return:
- ReleaseSyscallSemaphore(libPtr);
- API_STD_RETURN(error, 0);
- }
-
-
- LONG SAVEDS RAF6(_getsockopt,
- struct SocketBase *, libPtr, a6,
- LONG, s, d0,
- LONG, level, d1,
- LONG, name, d2,
- caddr_t, val, a0,
- ULONG *, avalsize, a1)
- #if 0
- {
- #endif
-
- struct socket *so;
- struct mbuf *m = NULL;
- ULONG valsize, error;
-
- CHECK_TASK();
- ObtainSyscallSemaphore(libPtr);
-
- if (error = getSock(libPtr, s, &so))
- goto Return;
-
- if (val)
- valsize = *avalsize;
- else
- valsize = 0;
-
- if ((error = sogetopt(so, level, name, &m)) == 0
- && val && valsize && m != NULL) {
- if (valsize > m->m_len) /* valsize is ULONG */
- valsize = m->m_len;
- bcopy(mtod(m, caddr_t), val, (u_int)valsize); /* aligned ? */
- *avalsize = valsize;
- }
- if (m != NULL)
- (void) m_free(m);
-
- Return:
- ReleaseSyscallSemaphore(libPtr);
- API_STD_RETURN(error, 0);
- }
-
- LONG SAVEDS RAF4(_getsockname,
- struct SocketBase *, libPtr, a6,
- LONG, fdes, d0,
- caddr_t, asa, a0,
- ULONG *, alen, a1)
- #if 0
- {
- #endif
-
- /*register*/
- struct socket *so;
- struct mbuf *m;
- LONG error;
-
- CHECK_TASK();
- ObtainSyscallSemaphore(libPtr);
-
- if (error = getSock(libPtr, fdes, &so))
- goto Return;
-
- m = m_getclr(M_WAIT, MT_SONAME);
- if (m == NULL) {
- error = ENOBUFS;
- goto Return;
- }
- if (error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0))
- goto bad;
- if (*alen > m->m_len)
- *alen = m->m_len;
- aligned_bcopy(mtod(m, caddr_t), (caddr_t)asa, (u_int)*alen);
-
- bad:
- m_freem(m);
-
- Return:
- ReleaseSyscallSemaphore(libPtr);
- API_STD_RETURN(error, 0);
- }
-
- LONG SAVEDS RAF4(_getpeername,
- struct SocketBase *, libPtr, a6,
- LONG, fdes, d0,
- caddr_t, asa, a0,
- ULONG *, alen, a1)
- #if 0
- {
- #endif
-
- /*register*/
- struct socket *so;
- struct mbuf *m;
- LONG error;
-
- CHECK_TASK();
- ObtainSyscallSemaphore(libPtr);
-
- if (error = getSock(libPtr, fdes, &so))
- goto Return;
-
- if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) {
- error = ENOTCONN;
- goto Return;
- }
-
- m = m_getclr(M_WAIT, MT_SONAME);
- if (m == NULL) {
- error = ENOBUFS;
- goto Return;
- }
-
- if (error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, 0, m, 0))
- goto bad;
- if (*alen > m->m_len)
- *alen = m->m_len;
- aligned_bcopy(mtod(m, caddr_t), (caddr_t)asa, (u_int)*alen);
-
- bad:
- m_freem(m);
-
- Return:
- ReleaseSyscallSemaphore(libPtr);
- API_STD_RETURN(error, 0);
- }
-
- LONG sockArgs(struct mbuf **mp,
- caddr_t buf, /* aligned */
- LONG buflen,
- LONG type)
- {
- register struct mbuf *m;
- LONG error = 0;
-
- if ((u_int)buflen > MLEN)
- return (EINVAL);
-
- m = m_get(M_WAIT, type);
- if (m == NULL)
- return (ENOBUFS);
- m->m_len = buflen;
-
- aligned_bcopy(buf, mtod(m, caddr_t), (u_int)buflen);
- *mp = m;
- if (type == MT_SONAME)
- mtod(m, struct sockaddr *)->sa_len = buflen;
-
- return (error);
- }
-
- /*
- * sdFind replaces old fdAlloc. This version now looks for free socket
- * from socket usage bitmask stored right after descriptor table
- */
-
- LONG sdFind(struct SocketBase * libPtr, LONG *fdp)
- {
- int bit, moffset;
- ULONG * smaskp;
- int mlongs = (libPtr->dTableSize - 1) / NFDBITS + 1;
-
- moffset = 0, smaskp = (ULONG *)(libPtr->dTable + libPtr->dTableSize);
- while (mlongs) {
- unsigned long cmask = *smaskp;
- unsigned long dmask = cmask + 1;
-
- if (dmask == 0) {
- mlongs--, smaskp++, moffset += 32;
- continue; /* current mask is full (cmask = 0xFFFFFFFF) */
- }
- cmask = ((cmask ^ dmask) >> 1) + 1; /* now only one bit set ! */
-
- bit = (cmask & 0xFFFF0000)? 16: 0;
- if (cmask & 0xFF00FF00) bit += 8;
- if (cmask & 0xF0F0F0F0) bit += 4;
- if (cmask & 0xCCCCCCCC) bit += 2;
- if (cmask & 0xAAAAAAAA) bit += 1;
-
- /*
- * Check if link library agrees with us on the next free fd...
- */
- if (libPtr->fdCallback)
- if (libPtr->fdCallback(moffset + bit, FDCB_CHECK)) {
- *smaskp |= cmask; /* mark this fd as used */
- continue; /* search for the next _bit_ */
- }
-
- if (moffset + bit >= libPtr->dTableSize)
- break;
- else {
- *fdp = moffset + bit;
- return 0;
- }
- }
- return (EMFILE);
- }
-